<template>
  <div id="addVersion">
    <slot name="title">
      <div v-if="title" class="moduleTitle">
        <span class="title">{{ title }}</span>
      </div>
    </slot>
    <div class="form-box">
      <a-form ref="formRef" :colon="false" :model="versionFrom" label-align="left" :rules="rules">
        <a-form-item label="版本号" name="versionName">
          <div class="mini-width">
            <a-input
              v-model:value="versionFrom.versionName"
              v-trim
              :maxlength="10"
              :disabled="props.type === 'edit'"
              placeholder="请输入版本号"
            />
          </div>
        </a-form-item>
        <a-form-item class="form-item" label="版本说明" name="versionDescribe">
          <a-textarea
            v-model:value="versionFrom.versionDescribe"
            v-trim
            show-count
            :auto-size="{ minRows: 8 }"
            :maxlength="200"
            placeholder="请输入版本说明"
          />
        </a-form-item>
        <a-form-item label="方式" name="versionType">
          <a-checkbox-group v-model:value="versionFrom.versionType" :options="wayOptions" @change="onVersionTypeChange" />
        </a-form-item>
        <a-form-item
          v-if="(versionFrom.versionType.length === 1 && versionFrom.versionType[0] === 1) || versionFrom.versionType.length === 2"
          label="API服务"
          class="required"
        >
          <a-form-item-rest>
            <div class="service-type-box">
              <div class="type-item">
                <div class="title">算法服务</div>
                <div class="value-box">
                  <a-form-item
                    :name="['apiServer', 'apiServiceId']"
                    :rules="[{ required: true, message: '请选择算法服务', trigger: 'change' }]"
                  >
                    <a-select
                      v-model:value="versionFrom.apiServer.apiServiceId"
                      :disabled="versionFrom.apiServer.disable"
                      placeholder="请选择算法服务"
                      :options="servicesOption"
                      :get-popup-container="(triggerNode: any) => triggerNode.parentNode"
                    />
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">QPS</div>
                <div class="value-box">
                  <a-form-item :name="['apiServer', 'qps']" :rules="[{ required: true, message: '请输入QPS', trigger: 'change' }]">
                    <a-input-number
                      id="inputNumber"
                      v-model:value="versionFrom.apiServer.qps"
                      :parser="(text: any)=>/^\d+$/.test(text)?text:1"
                      class="inputNumber"
                      placeholder="请输入QPS"
                      :max="100000"
                      :min="1"
                      :maxlength="6"
                    />
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">API文档</div>
                <div class="value-box">
                  <a-form-item
                    :name="['apiServer', 'documentUrl']"
                    :rules="[{ required: true, message: '请上传API文档', trigger: 'change' }]"
                  >
                    <file-upload
                      v-model:file-url="versionFrom.apiServer.documentUrl"
                      class="file-upload"
                      :max-count="1"
                      :is-preview="false"
                      suffix="doc"
                      accept="pdf"
                      module-prefix="algo"
                      @upload-success-after="onUpdateFile('api')"
                    >
                      <a-button type="dashed" size="small" class="icon-with-btn btn-mini">
                        <i class="iconfont icon-upload-line"></i>
                        上传
                      </a-button>
                    </file-upload>
                  </a-form-item>
                </div>
              </div>
            </div>
          </a-form-item-rest>
        </a-form-item>
        <a-form-item
          v-if="(versionFrom.versionType.length === 1 && versionFrom.versionType[0] === 2) || versionFrom.versionType.length === 2"
          label="SDK服务"
          class="required"
        >
          <a-form-item-rest>
            <div
              v-for="(item, index) in versionFrom.sdkServer"
              :key="index"
              class="service-type-box service-type-box-list"
              :style="[versionFrom.sdkServer.length === index + 1 ? 'marginBottom: 0' : '']"
            >
              <div class="type-item type-title-item">
                <a-button
                  v-if="versionFrom.sdkServer.length > 1"
                  type="text"
                  class="delete-btn icon-only-btn"
                  :disabled="item.disable"
                  @click="!item.disable ? handleRemoveSDK(index) : ''"
                >
                  <i class="iconfont icon-delete-bin-6-fill"></i>
                </a-button>
              </div>
              <div class="type-item">
                <div class="title">平台</div>
                <div class="value-box">
                  <a-form-item
                    :name="['sdkServer', index, 'platformId']"
                    :rules="[{ required: true, message: '请选择平台', trigger: 'change' }]"
                  >
                    <a-select
                      v-model:value="item.platformId"
                      :disabled="item.disable"
                      placeholder="请选择平台"
                      :options="platOption"
                      :get-popup-container="(triggerNode: any) => triggerNode.parentNode"
                      @change="(value: any) => onChangePlat(value, item, index)"
                    />
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">语言</div>
                <div class="value-box">
                  <a-form-item
                    :name="['sdkServer', index, 'languageId']"
                    :rules="[{ required: true, message: '请选择语言', trigger: 'change' }]"
                  >
                    <a-select
                      v-model:value="item.languageId"
                      :disabled="item.disable || !item.platformId"
                      placeholder="请选择语言"
                      :options="item.langOptions"
                      :get-popup-container="(triggerNode: any) => triggerNode.parentNode"
                    />
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">授权方式</div>
                <div class="value-box">
                  <a-form-item
                    :name="['sdkServer', index, 'activeMethodIds']"
                    :rules="[{ required: true, message: '请选择授权方式', trigger: 'change' }]"
                  >
                    <a-checkbox-group v-model:value="item.activeMethodIds" :options="item.authOptions" />
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">SDK文件</div>
                <div class="value-box">
                  <a-form-item
                    :name="['sdkServer', index, 'sdkServiceUrl']"
                    :rules="[{ required: true, message: '请上传SDK文件', trigger: 'change' }]"
                  >
                    <file-upload-sdk
                      v-model:file-url="item.sdkServiceUrl"
                      v-model:sign="item.sign"
                      accept="tar.gz,zip"
                      class="file-upload"
                      :is-preview="false"
                      :disabled="item.disable"
                    >
                      <a-button type="dashed" size="small" class="icon-with-btn btn-mini">
                        <i class="iconfont icon-upload-line"></i>
                        上传
                      </a-button>
                    </file-upload-sdk>
                  </a-form-item>
                </div>
              </div>
              <div class="type-item">
                <div class="title">SDK文档</div>
                <div class="value-box">
                  <a-form-item
                    :name="['sdkServer', index, 'documentUrl']"
                    :rules="[{ required: true, message: '请上传SDK文档', trigger: 'change' }]"
                  >
                    <file-upload
                      v-model:file-url="item.documentUrl"
                      class="file-upload"
                      :max-count="1"
                      :is-preview="false"
                      suffix="doc"
                      accept="pdf"
                      module-prefix="algo"
                      @upload-success-after="onUpdateFile('sdk', index)"
                    >
                      <a-button type="dashed" size="small" class="icon-with-btn btn-mini">
                        <i class="iconfont icon-upload-line"></i>
                        上传
                      </a-button>
                    </file-upload>
                  </a-form-item>
                </div>
              </div>
            </div>
            <div class="demo-add" @click="handleAddSDK"><i class="iconfont icon-add-line"></i></div>
          </a-form-item-rest>
        </a-form-item>
      </a-form>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { message } from 'ant-design-vue'
  import { Rule } from 'ant-design-vue/lib/form'
  import { cloneDeep, regex } from 'g6-fn'
  import { onMounted, reactive, ref } from 'vue'
  import { useRequest } from 'vue-request'

  import { algoDepotApi } from '@/services/api'

  import FileUploadSdk from './file-upload-sdk.vue'

  export interface Props {
    type?: 'add' | 'edit'
    title?: string
  }
  const props = withDefaults(defineProps<Props>(), {
    type: 'add',
    title: '上传版本'
  })

  const formRef = ref()
  const servicesOption = ref([])
  const platOption = ref<any[]>([])
  const authOptions = ref<any[]>([])
  const wayOptions = ref<any[]>([
    { label: 'API', value: 1, disabled: false },
    { label: 'SDK', value: 2, disabled: false }
  ])
  const versionBaseData = {
    type: 1,
    qps: undefined,
    apiServiceId: undefined,
    documentUrl: undefined,
    languageId: undefined,
    activeMethodIds: ['1', '2'],
    platformId: undefined,
    documentName: undefined,
    sdkServiceUrl: undefined,
    disable: false,
    langOptions: [],
    updateDocumentFlag: false,
    sign: ''
  }
  let versionFrom = reactive({
    versionName: '',
    versionDescribe: '',
    versionType: [] as any[],
    apiServer: { ...versionBaseData, type: 1 },
    sdkServer: [{ ...versionBaseData, type: 2, authOptions: authOptions.value }],
    createOperateMethodDtoS: [] as any[]
  })
  const versionFromInfo = cloneDeep(versionFrom)
  onMounted(() => {
    getPlatform()
    getActivationMethods()
    getServices()
  })

  const validateApi = () => {
    const value = versionFrom.apiServer
    if (!value) {
      return Promise.reject('请完善API服务')
    }
    if (!value.qps || !value.documentUrl || !value.apiServiceId) {
      return Promise.reject('请完善API服务')
    }
    return Promise.resolve()
  }
  const validateSdk = () => {
    const value = versionFrom.sdkServer
    for (let index = 0; index < value.length; index++) {
      const element = value[index]
      if (!element.sdkServiceUrl || !element.languageId || !element.platformId || !element.documentUrl || !element.activeMethodIds.length) {
        return Promise.reject('请完善SDK服务')
      }
    }
    return Promise.resolve()
  }
  const rules: Record<string, Rule[]> = {
    versionName: [
      { required: true, message: '请输入版本号', trigger: 'change' },
      {
        pattern: regex.version,
        message: '仅支持数字和小数点,且以数字结尾',
        trigger: 'change'
      }
    ],
    apiService: [{ required: true, validator: validateApi, trigger: 'change' }],
    sdkService: [{ required: true, validator: validateSdk, trigger: 'change' }],
    versionType: [{ required: true, message: '请选择方式', trigger: 'change' }],
    versionDescribe: [{ required: true, message: '请输入版本说明', trigger: 'change' }]
  }

  // 获取算法列表
  const { runAsync: getServices } = useRequest(algoDepotApi.getServices, {
    onSuccess: (res: any) => {
      servicesOption.value = res.data.map((item: any) => {
        return { label: item.serviceName, value: item.id }
      })
    }
  })

  // 获取激活方式
  const { runAsync: getActivationMethods } = useRequest(algoDepotApi.getActivationMethods, {
    onSuccess: (res: any) => {
      authOptions.value = res.data.map((item: any) => {
        return { label: item.typeName, value: item.id }
      })
      versionFrom.sdkServer[0].authOptions = authOptions.value
    }
  })

  // 切换平台
  const onChangePlat = (value: any, row: any, index: any) => {
    // 重置已选择的语言
    row.languageId = undefined
    versionFrom.sdkServer[index].langOptions = getPlatDownLang(value)
  }
  // 根据平台id获取语言id
  const getPlatDownLang = (id: string) => {
    const data = langAllList.value.find(item => {
      return Number(item.id) === Number(id)
    })
    return data.childList.map((item: any) => {
      return { label: item.value, value: item.id }
    })
  }
  // 获取平台语言
  const langAllList = ref<any[]>([])
  const { runAsync: getPlatform } = useRequest(algoDepotApi.getPlatform, {
    onSuccess: (res: any) => {
      platOption.value = res.data.map((item: any) => {
        return { label: item.value, value: item.id }
      })
      langAllList.value = res.data
    }
  })

  const onVersionTypeChange = () => {}
  const handleAddSDK = () => {
    versionFrom.sdkServer.push({ ...versionBaseData, type: 2, authOptions: authOptions.value })
  }
  const handleRemoveSDK = (index: number) => {
    versionFrom.sdkServer.splice(index, 1)
    formRef.value.validateFields()
  }

  // 修改版本时监听文档是否改变
  const onUpdateFile = (type: 'sdk' | 'api', index?: number) => {
    if (props.type === 'add') {
      return
    }
    if (type === 'sdk') {
      versionFrom.sdkServer[index!].updateDocumentFlag = true
      return
    }
    versionFrom.apiServer.updateDocumentFlag = true
  }

  const getVersionFrom = () => {
    return new Promise(resolve => {
      formRef.value.validateFields().then(() => {
        const { versionType, apiServer, sdkServer } = versionFrom
        if (versionType.length === 1 && versionType[0] === 1) {
          versionFrom.createOperateMethodDtoS = [{ ...apiServer }]
        }
        if (versionType.length === 1 && versionType[0] === 2) {
          versionFrom.createOperateMethodDtoS = [...sdkServer]
        }
        if (versionType.length === 2) {
          versionFrom.createOperateMethodDtoS = [{ ...apiServer }, ...sdkServer]
        }

        resolve(versionFrom)
      })
    })
  }

  // 设置表单数据
  const setVersionFrom = (data: any) => {
    try {
      versionFrom.versionName = data.versionName
      versionFrom.versionDescribe = data.versionDescribe
      versionFrom.versionType = data.operateMethodTypes
      wayOptions.value = wayOptions.value.map(item => {
        if (versionFrom.versionType.includes(item.value)) {
          return { ...item, disabled: true }
        }
        return item
      })
      let sdkServer: any[] = []
      data.operateMethodInfoVOS.forEach((element: any) => {
        if (Number(element.type) === 1) {
          element.apiServiceId = Number(element.apiServiceId) as any
          element.disable = true
          versionFrom.apiServer = element
        } else {
          element.disable = true
          element.activeMethodIds = element.activationTypeId.map((item: any) => item.toString())
          element.authOptions = authOptions.value.map((item: any) => {
            if (element.activationTypeId.includes(Number(item.value))) {
              return { ...item, disabled: true }
            }
            return item
          })
          element.langOptions = getPlatDownLang(element.platformId)
          sdkServer.push(element)
        }
      })
      sdkServer.length > 0 ? (versionFrom.sdkServer = sdkServer) : null
    } catch (error) {
      message.error('数据解析错误')
    }
  }

  const resetFields = () => {
    formRef.value.resetFields()
    Object.assign(versionFrom, versionFromInfo)
    versionFrom.apiServer.documentUrl = undefined
    versionFrom.sdkServer = versionFrom.sdkServer.map(item => {
      return { ...item, documentUrl: undefined, sdkServiceUrl: undefined }
    })
  }

  defineExpose({
    versionFrom,
    getVersionFrom: getVersionFrom,
    setVersionFrom: setVersionFrom,
    resetFields: resetFields
  })
</script>

<style lang="less" scoped>
  input {
    width: 440px !important;
  }

  .form-item {
    :deep(.ant-form-item-control-input) {
      width: 440px !important;
    }
  }

  :deep(.ant-upload-list-text-container) {
    transition: none;
  }

  :deep(.ant-upload-list) {
    display: inline-block;
    margin-left: 0 !important;
    min-width: 272px;
  }

  :deep(.ant-anchor-ink-ball) {
    left: -50%;
    width: 2px;
    height: 22px;
    border-radius: 0;
    transform: translate(0, -7px);
  }

  :deep(.ant-upload-picture-card-wrapper) {
    width: 140px;
  }

  :deep(.ant-form-item) {
    margin-bottom: 64px;
  }

  :deep(.ant-form-item-label > label) {
    min-width: 120px;
  }

  // :deep(.ant-input-textarea-show-count::after) {
  //   position: absolute;
  //   right: 12px;
  //   bottom: 8px;
  // }

  .moduleTitle {
    display: flex;
    align-items: center;
    padding: 0 0 60px;

    .icon {
      font-size: 32px;
      color: rgba(65, 84, 209, 1);
    }

    .title {
      .font20b();

      position: relative;
      margin-left: 16px;
      color: rgba(16, 16, 20, 0.95);

      &::before {
        position: absolute;
        top: 50%;
        left: -16px;
        width: 3px;
        height: 22px;
        background: #1868e9;
        border-radius: 0 2px 2px 0;
        content: '';
        transform: translateY(-50%);
        flex: none;
        order: 0;
        align-self: stretch;
        flex-grow: 0;
      }
    }
  }

  .disable {
    color: rgba(25, 25, 48, 0.2);
  }

  .form-box {
    margin-bottom: 120px;
    max-width: 752px;

    .scene-upload {
      margin-top: 16px;

      :deep(.upload-info) {
        display: flex;
        justify-content: flex-end;
      }
    }

    .preview-upload {
      :deep(.ant-upload.ant-upload-select-picture-card) {
        width: 140px;
        height: 140px;
        font-size: 14px;
        color: rgba(25, 25, 48, 0.75);
        background-color: #fff;
        border: 1px solid rgba(0, 0, 0, 0.12);
        border-radius: 6px;

        .ant-upload-text {
          margin-top: 13px;
          font-size: 14px;
          color: rgba(25, 25, 48, 0.75);
        }
      }
    }

    .tag-box {
      display: flex;
      align-items: center;
      color: rgba(65, 84, 209, 1);

      .tag-list {
        margin-left: 40px;

        .tag {
          display: inline-block;
          overflow: hidden;
          padding: 3px 6px;
          margin-right: 16px;
          line-height: 22px;
          text-overflow: ellipsis;
          white-space: nowrap;
          border: 1px solid rgba(0, 0, 0, 0.05);
          border-radius: 6px;

          &.typeTag {
            color: #4686ed;
            background: rgba(65, 84, 209, 0.08);
          }

          &.personalizedTag {
            color: #d61860;
            background: rgba(214, 24, 96, 0.08);
          }

          .close {
            padding-left: 6px;
            font-size: 12px;
            cursor: pointer;
            color: rgba(25, 25, 48, 0.45);
          }
        }
      }
    }

    .demo-info-list {
      .demo-info {
        position: relative;
        padding: 12px 180px 20px 16px;
        margin-bottom: 16px;
        background: #fafafa;

        .input-box {
          margin-bottom: 16px;
        }

        .tools {
          position: absolute;
          top: 12px;
          right: 16px;
          display: flex;
          align-items: center;
          height: 22px;
          font-size: 18px;

          span {
            cursor: pointer;
          }

          .mid-line {
            display: inline-block;
            margin: 0 16px;
            width: 1px;
            height: 100%;
            background: #ebebeb;
          }

          .disable {
            color: rgba(25, 25, 48, 0.2);
          }

          .down-btn {
            margin-left: 25px;
          }
        }
      }
    }

    .service-type-box {
      position: relative;
      padding: 16px 0 24px 24px;
      background: #fafafa;
      border-radius: 6px;

      :deep(.ant-form-item) {
        margin-bottom: 0;
      }

      .delete-btn {
        position: absolute;
        top: 12px;
        right: 25px;
        font-size: 14px;
      }

      .type-item {
        display: flex;
        align-items: center;
        padding-right: 204px;
        margin-bottom: 24px;

        .title {
          margin-right: 8px;
          min-width: 90px;
          .font14b();
        }

        .value-box {
          width: 100%;

          .inputNumber {
            width: 150px;
          }

          .file-upload {
            width: 306px;
          }
        }
      }

      .type-title-item {
        padding-right: 0;
        margin-bottom: 0;
      }
    }

    .service-type-box-list {
      margin-bottom: 64px;
    }

    .service-type-box-list:last-child {
      margin-bottom: 0;
    }
  }

  .demo-add {
    margin-top: 16px;
    width: 38px;
    height: 38px;
    text-align: center;
    border: 1px solid #d9d9db;
    border-radius: 6px;
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.043);
    line-height: 38px;
    cursor: pointer;
  }
</style>
